//@ts-ignore
import PCMPlayer from "./pcm-player.js";
let onQueueEmpty: (() => void) | null = null;
let onTextMessage: ((data: any) => void) | null = null;
let onFirstMessage: (() => void) | null = null;
let ws: WebSocket | null = null;
let isFirst: boolean = true;
let player: PCMPlayer | null = null;
let isClosed: boolean = false;
export function connectAndStreamAudio(
  text: string,
  sessionId: string | null = null,
  useAI: boolean = true,
) {
  isFirst = true;
  isClosed = false;
  player = new PCMPlayer({
    inputCodec: "Int16",
    channels: 1,
    sampleRate: 22050,
    flushTime: 300,
    onended: onQueueEmpty,
  });
  if (ws && ws.readyState === WebSocket.OPEN) {
    ws.close();
  }
  ws = new WebSocket(
    `${import.meta.env.VITE_WS_TYPE}://${
      import.meta.env.VITE_DEVELOPMENT_URL
    }/api/ws/chat`
  );
  ws.binaryType = "arraybuffer";

  ws.onopen = () => {
    if (!ws) return;
    if (useAI) {
      ws.send(
        JSON.stringify({
          text: text,
          useAI: true,
          session_id: sessionId,
        })
      );
    } else {
      ws.send(JSON.stringify({ text: text, useAI: false }));
    }
  };

  ws.onmessage = (event) => {
    const data = event.data;
    if (typeof data === "string") {
      const parsedData = JSON.parse(data);
      if (parsedData.type === "end") {
        isClosed = true;
      }
      if (onTextMessage != null) {
        onTextMessage(parsedData);
      }
    } else if (data instanceof ArrayBuffer) {
      if (isFirst && onFirstMessage != null) {
        onFirstMessage();
        isFirst = false;
      }
      player.feed(data);
    }
  };

  ws.onclose = () => {
    console.log("WebSocket connection closed");
  };

  ws.onerror = (error) => {
    console.error("WebSocket error", error);
  };
}

export const stopAudio = () => {
  if (player != null) {
    player.destroy();
    player = null;
    if (typeof onQueueEmpty === "function") {
      isClosed = true;
      onQueueEmpty();
    }
  }
};

export const setOnQueueEmpty = (callback: () => void) => {
  onQueueEmpty = () => {
    if (isClosed) callback();
  };
};

export const setonFirstMessage = (callback: () => void) => {
  onFirstMessage = () => {
    callback();
  };
};

export const setOnTextMessage = (callback: (data: any) => void) => {
  onTextMessage = (data) => {
    callback(data);
  };
};

export const stopStreaming = () => {
  if (ws && ws.readyState === WebSocket.OPEN) {
    ws.close();
  }
  stopAudio();
};